package co.baiku.boot.wechat.config.mp;

import co.baiku.boot.wechat.enums.StorageType;
import co.baiku.boot.wechat.properties.WxMpProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps;
import me.chanjar.weixin.common.redis.WxRedisOps;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.WxMpHostConfig;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;

/**
 * 微信公众号存储策略自动配置.
 *
 * @author someone
 */
@Slf4j
@Configuration
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "wx.mp", value = "enabled", havingValue = "true")
public class WxMpStorageAutoConfiguration {
    private final ApplicationContext applicationContext;

    private final WxMpProperties wxMpProperties;

    @Bean
    @ConditionalOnMissingBean(WxMpConfigStorage.class)
    public WxMpConfigStorage wxMpConfigStorage() {
        StorageType type = wxMpProperties.getConfigStorage().getType();
        WxMpConfigStorage config;
        switch (type) {
            case RedisTemplate:
                config = redisTemplateConfigStorage();
                break;
            default:
                config = defaultConfigStorage();
                break;
        }
        // wx host config
        if (null != wxMpProperties.getHosts() && StringUtils.isNotEmpty(wxMpProperties.getHosts().getApiHost())) {
            WxMpHostConfig hostConfig = new WxMpHostConfig();
            hostConfig.setApiHost(wxMpProperties.getHosts().getApiHost());
            hostConfig.setMpHost(wxMpProperties.getHosts().getMpHost());
            hostConfig.setOpenHost(wxMpProperties.getHosts().getOpenHost());
            config.setHostConfig(hostConfig);
        }
        return config;
    }

    private WxMpConfigStorage defaultConfigStorage() {
        WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
        setWxMpInfo(config);
        return config;
    }

    private WxMpConfigStorage redisTemplateConfigStorage() {
        StringRedisTemplate redisTemplate = null;
        try {
            redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        try {
            if (null == redisTemplate) {
                redisTemplate = (StringRedisTemplate) applicationContext.getBean("stringRedisTemplate");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        if (null == redisTemplate) {
            redisTemplate = (StringRedisTemplate) applicationContext.getBean("redisTemplate");
        }

        WxRedisOps redisOps = new RedisTemplateWxRedisOps(redisTemplate);
        WxMpRedisConfigImpl wxMpRedisConfig = new WxMpRedisConfigImpl(redisOps,
                wxMpProperties.getConfigStorage().getKeyPrefix());

        setWxMpInfo(wxMpRedisConfig);
        return wxMpRedisConfig;
    }

    private void setWxMpInfo(WxMpDefaultConfigImpl config) {
        WxMpProperties properties = wxMpProperties;
        WxMpProperties.ConfigStorage configStorageProperties = properties.getConfigStorage();
        config.setAppId(properties.getAppid());
        config.setSecret(properties.getSecret());
        config.setToken(properties.getToken());
        config.setAesKey(properties.getAesKey());

        config.setHttpProxyHost(configStorageProperties.getHttpProxyHost());
        config.setHttpProxyUsername(configStorageProperties.getHttpProxyUsername());
        config.setHttpProxyPassword(configStorageProperties.getHttpProxyPassword());
        if (configStorageProperties.getHttpProxyPort() != null) {
            config.setHttpProxyPort(configStorageProperties.getHttpProxyPort());
        }
    }

}
